<?php
// +----------------------------------------------------------------------
// | Author: July
// +----------------------------------------------------------------------
// | 创建时间: 2023-12-27 20:39:42
// +----------------------------------------------------------------------
// | 导出相关操作
// +----------------------------------------------------------------------

namespace july\julyadmin\common\logic;

use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;

class ExportLogic
{
    // 文件名，不包括后缀，如：财务报表
    protected $title = '';
    // 报表头数组
    protected $headers = [];
    // 内容数组
    protected $data = [];
    //导出目录
    protected $dir = '';
    /**
     * 初始化
     * @Author   july
     * @DateTime 2023-09-03
     * @param    string     $title    文件名，不包括后缀，如：财务报表
     * @param    array      $headers 报表头数组，如：
     * $headers = ['姓名', '年龄', '手机号'];
     * @param    array      $data    内容数组，如：
     * $data    = [
     *   ['张三', '32', '123456'],
     *   ['李四', '11', '123456'],
     *   ['王二', '23', '123456'],
     *   ['张飞', '33', '123456'],
     *   ['刘备', '32', '123456'],
     *];
     */
    public function __construct($title = '', $headers = [], $data = [])
    {
        $title         = str_replace([' ', '.', '!', '@', '#', '＃', '$', '%', '^', '&', '*', '(', ')', '{', '}', '【', '】', '[', ']'], '', trim($title));
        $this->title   = $title;
        $this->headers = $headers;
        $this->data    = $data;

        //创建目录
        $this->dir = app()->getRootPath() . '/public/export/' . date('Ymd') . '/';
        if (!is_dir($this->dir)) {
            if (!mkdir($this->dir, 0755, true)) {
                return json(['code' => 0, 'msg' => '创建目录' . $this->dir . '失败']);
            }
        }
    }

    /**
     * 追加导出内容
     * @Author   july
     * @DateTime 2023-09-03
     * @param    array     $data 导出内容,如：
     * $data    = [
     *   ['张三', '32', '123456'],
     *   ['李四', '11', '123456'],
     *   ['王二', '23', '123456'],
     *   ['张飞', '33', '123456'],
     *   ['刘备', '32', '123456'],
     *];
     */
    public function appendData($data = [])
    {
        $this->data = array_merge($this->data, $data);
    }

    /**
     * 导出Csv
     * @Author   july
     * @DateTime 2023-09-03
     */
    public function exportCsv()
    {
        $fname = $this->dir . $this->title . ".csv";
        if ($this->csvExists($this->title)) {
            $this->headers = [];
        }

        //追加模式打开，因为一个请求可能会超时，导致没有全部写入，有时候我们可能会需要处理多个请求，写入同一个文件，所以这里用追加的方式写入
        $fp = fopen($fname, 'a');
        if ($this->headers) {
            fputcsv($fp, $this->headers);
        }
        foreach ($this->data as $row) {
            $data = [];
            foreach ($row as $d) {
                //处理数字，不要显示科学计数法
                if (is_numeric($d) && !strstr($d, '.')) {
                    $d .= "\t";
                }
                $data[] = $d;
            }
            fputcsv($fp, $data);
            unset($data);
        }
        fclose($fp);
        $file = str_replace(app()->getRootPath() . '/public', '', $fname);
        return ['code' => 1, 'msg' => '导出成功', 'data' => ['url' => $file]];
    }

    /**
     * 判断导出的文件是否存在
     * @Author   july
     * @DateTime 2023-09-03
     * @param    string     $title 文件名，不包含后缀，如：财务报表
     * @return   boolean           存在返回true，否则返回false
     */
    public function csvExists($title = '')
    {
        $fname = $this->dir . $this->title . ".csv";
        if (file_exists($fname)) {
            return true;
        } else {
            return false;
        }
    }
    /**
     * 删除csv文件
     * @Author   july
     * @DateTime 2023-09-03
     * @param    string     $title 文件名，不包含后缀，如：财务报表
     * @return   boolean            删除成功返回true，否则返回false
     */
    public function csvDelete($title = '')
    {
        $fname = $this->dir . $this->title . ".csv";
        if (file_exists($fname)) {
            if (unlink($fname)) {
                return true;
            } else {
                return false;
            }
        } else {
            return true;
        }
    }

    /**
     * 导出excel
     * @Author   july
     * @DateTime 2023-09-03
     */
    public function exportExcel()
    {
        $fname = $this->dir . $this->title . ".xlsx";
        if ($this->excelExists($this->title)) {
            $this->headers = [];
        }

        if ($this->headers) {
            $this->data = array_merge([$this->headers], $this->data);
        }
        if ($this->excelExists($this->title)) {
            //打开文件
            $spreadsheet = IOFactory::load($fname);
        } else {
            //创建新的工作簿
            $spreadsheet = new Spreadsheet();
        }
        //创建工作表
        $sheet = $spreadsheet->getActiveSheet();
        if ($this->excelExists($this->title)) {
            //设置行和列
            $rowCount = $sheet->getHighestRow() + 1;
            foreach ($this->data as $row) {
                $colCount = 1;
                foreach ($row as $d) {
                    //处理数字，不要显示科学计数法
                    if (is_numeric($d) && !strstr($d, '.')) {
                        $d .= "\t";
                    }
                    //设置单元格的值为数据
                    $sheet->getCellByColumnAndRow($colCount, $rowCount)->setValue($d);
                    $colCount++;
                }
                $rowCount++;
            }

            //导出数据
            $writer = new Xlsx($spreadsheet, 'Excel2007');
            $writer->save($fname); // 保存Excel文件
        } else {
            //设置行和列
            $rowCount = 1;
            foreach ($this->data as $row) {
                $colCount = 1;
                foreach ($row as $d) {
                    //处理数字，不要显示科学计数法
                    if (is_numeric($d) && !strstr($d, '.')) {
                        $d .= "\t";
                    }
                    //设置单元格的值为数据
                    $sheet->getCellByColumnAndRow($colCount, $rowCount)->setValue($d);
                    $colCount++;
                }
                $rowCount++;
            }

            //导出数据
            $writer = new Xlsx($spreadsheet, 'Excel2007');
            $writer->save($fname); // 保存Excel文件
        }

        $file = str_replace(app()->getRootPath() . '/public', '', $fname);
        return ['code' => 1, 'msg' => '导出成功', 'data' => ['url' => $file]];
    }

    /**
     * 判断导出的文件是否存在
     * @Author   july
     * @DateTime 2023-09-03
     * @param    string     $title 文件名，不包含后缀，如：财务报表
     * @return   boolean           存在返回true，否则返回false
     */
    public function excelExists($title = '')
    {
        $fname = $this->dir . $this->title . ".xlsx";
        if (file_exists($fname)) {
            return true;
        } else {
            return false;
        }
    }
    /**
     * 删除excel文件
     * @Author   july
     * @DateTime 2023-09-03
     * @param    string     $title 文件名，不包含后缀，如：财务报表
     * @return   boolean            删除成功返回true，否则返回false
     */
    public function excelDelete($title = '')
    {
        $fname = $this->dir . $this->title . ".xlsx";
        if (file_exists($fname)) {
            if (unlink($fname)) {
                return true;
            } else {
                return false;
            }
        } else {
            return true;
        }
    }
}
